import { Inject, Injectable } from '@nestjs/common';
import { IsNull, Not, Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { UpdateUserDto } from './dto/update-user.dto';
import { ConfigService } from '@nestjs/config';
import { getRedisKey, safeOutput } from 'src/utils';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { NotifyService } from 'src/notify/notify.service';
import { paginate } from 'nestjs-typeorm-paginate';

@Injectable()
export class UserService {
    constructor(
        @InjectRepository(User) private userRepository: Repository<User>,
        @Inject(CACHE_MANAGER) private cacheManager: Cache,
        private configService: ConfigService,
        private notifyService: NotifyService,
    ) { }

    /**
     * 新增用户
     *
     * @param {*} userData 用户数据
     * @return {*}
     * @memberof UserService
     */
    async create(userData: any): Promise<any> {
        // 创建User实体实例以触发@BeforeInsert钩子
        const user = this.userRepository.create(userData);
        return await this.userRepository.save(user);
    }

    /**
     * 查询用户信息
     *
     * @param {string} obj 筛选条件
     * @return {*} 用户信息
     * @memberof UserService
     */
    async findUser(obj: any): Promise<any> {
        const userInfo = await this.userRepository.findOne({ where: { ...obj } });
        if (!userInfo) return null;

        return userInfo;
    }

    /**
     * 查询用户是否存在
     *
     * @param {*} obj 格式: {id: xxx}/{phone: xxx}/{email: xxx}
     * @return {*} userInfo
     * @memberof UserService
     */
    async checkExist(obj: any): Promise<any> {
        return await this.userRepository.findOne({
            where: { ...obj, deleted_at: IsNull() },
        });
    }

    /**
     * 更新用户信息，同时更新Redis信息
     *
     * @memberof UserService
     */
    async updateInfoWithCache(id: string, data: UpdateUserDto): Promise<any> {
        const redisKey = getRedisKey(id.toString(), 'user', 'info');
        const redisExist = await this.cacheManager.store.get(redisKey);

        // 更新MySQL数据
        await this.userRepository.update(id, data);

        let userInfo = await this.userRepository.findOne({ where: { id } });
        if (redisExist) { // 如果redis没过期，那么也更新redis
            userInfo = safeOutput(userInfo);
            await this.cacheManager.store.set(redisKey, userInfo);
        }

        return userInfo;
    }

    /**
     * 只更新用户数据
     *
     * @param {string} id 用户id
     * @param {UpdateUserDto} data 更新数据
     * @return {*}
     * @memberof UserService
     */
    async onlyUpdate(id: string, data: UpdateUserDto): Promise<any> {
        return await this.userRepository.update(id, data);
    }

    /**
     * 注销账号
     *
     * @param {string} user_id 用户id
     * @return {*}
     * @memberof UserService
     */
    async deleteUser(user_id: string): Promise<boolean> {
        // 1. 删除用户
        await this.userRepository.softDelete(user_id);
        // 2. 删除redis token
        const userRedisKey = getRedisKey(user_id, 'user', 'info');
        await this.cacheManager.store.del(userRedisKey);
        await this.cacheManager.store.del(`${user_id}_token`);
        await this.cacheManager.store.del(`${user_id}_refresh`);
        // 3. 删除钱包、删除账单、删除绘画、对话等数据，通知管理员异步操作即可
        this.notifyService.wxSend(`用户【${user_id}】已注销，请及时删除钱包、账单、绘图、对话等数据`);

        return true;
    }

}
